{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 数据预处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/malele/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n",
      "Using TensorFlow backend.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X_train shape: (3827, 200, 6, 1)\n",
      "Y_train shape: (3827, 16)\n",
      "X_test shape: (957, 200, 6, 1)\n",
      "Y_test shape: (957, 16)\n"
     ]
    }
   ],
   "source": [
    "import h5py\n",
    "import numpy as np\n",
    "import tensorflow as tf \n",
    "import keras\n",
    "from keras.layers import Input, Dense, Dropout, Activation, BatchNormalization,concatenate, Flatten, Conv2D, AveragePooling2D, MaxPooling2D\n",
    "from keras.models import Model\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "def convert_to_one_hot(Y, C):\n",
    "    Y = np.eye(C)[Y.reshape(-1)].T\n",
    "    return Y\n",
    "\n",
    "file = h5py.File('DB3//DB3_S1_image.h5','r')\n",
    "imageData   = file['imageData'][:]\n",
    "imageData   = imageData*2000\n",
    "imageLabel  = file['imageLabel'][:]  \n",
    "file.close()\n",
    "\n",
    "# 随机打乱数据和标签\n",
    "N = imageData.shape[0]\n",
    "index = np.random.permutation(N)\n",
    "data  = imageData[index,:,:]\n",
    "label = imageLabel[index]\n",
    "\n",
    "# 对数据升维,标签one-hot\n",
    "data  = np.expand_dims(data, axis=3)\n",
    "label = convert_to_one_hot(label,16).T\n",
    "\n",
    "# 划分数据集\n",
    "N = data.shape[0]\n",
    "num_train = round(N*0.8)\n",
    "X_train = data[0:num_train,:,:,:]\n",
    "Y_train = label[0:num_train,:]\n",
    "X_test  = data[num_train:N,:,:,:]\n",
    "Y_test  = label[num_train:N,:]\n",
    "\n",
    "print (\"X_train shape: \" + str(X_train.shape))\n",
    "print (\"Y_train shape: \" + str(Y_train.shape))\n",
    "print (\"X_test shape: \" + str(X_test.shape))\n",
    "print (\"Y_test shape: \" + str(Y_test.shape))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#写一个LossHistory类，保存loss和acc\n",
    "class LossHistory(keras.callbacks.Callback):\n",
    "    def on_train_begin(self, logs={}):\n",
    "        self.losses = {'batch':[], 'epoch':[]}\n",
    "        self.accuracy = {'batch':[], 'epoch':[]}\n",
    "        self.val_loss = {'batch':[], 'epoch':[]}\n",
    "        self.val_acc = {'batch':[], 'epoch':[]}\n",
    "\n",
    "    def on_batch_end(self, batch, logs={}):\n",
    "        self.losses['batch'].append(logs.get('loss'))\n",
    "        self.accuracy['batch'].append(logs.get('acc'))\n",
    "        self.val_loss['batch'].append(logs.get('val_loss'))\n",
    "        self.val_acc['batch'].append(logs.get('val_acc'))\n",
    "\n",
    "    def on_epoch_end(self, batch, logs={}):\n",
    "        self.losses['epoch'].append(logs.get('loss'))\n",
    "        self.accuracy['epoch'].append(logs.get('acc'))\n",
    "        self.val_loss['epoch'].append(logs.get('val_loss'))\n",
    "        self.val_acc['epoch'].append(logs.get('val_acc'))\n",
    "\n",
    "    def loss_plot(self, loss_type):\n",
    "        iters = range(len(self.losses[loss_type]))\n",
    "        plt.figure()\n",
    "        # acc\n",
    "        plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')\n",
    "        # loss\n",
    "        plt.plot(iters, self.losses[loss_type], 'g', label='train loss')\n",
    "        if loss_type == 'epoch':\n",
    "            # val_acc\n",
    "            plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')\n",
    "            # val_loss\n",
    "            plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')\n",
    "        plt.grid(True)\n",
    "        plt.xlabel(loss_type)\n",
    "        plt.ylabel('acc-loss')\n",
    "        plt.legend(loc=\"upper right\")\n",
    "        plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 建立模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__________________________________________________________________________________________________\n",
      "Layer (type)                    Output Shape         Param #     Connected to                     \n",
      "==================================================================================================\n",
      "input_1 (InputLayer)            (None, 200, 6, 1)    0                                            \n",
      "__________________________________________________________________________________________________\n",
      "conv2d_1 (Conv2D)               (None, 181, 4, 32)   1952        input_1[0][0]                    \n",
      "__________________________________________________________________________________________________\n",
      "conv2d_3 (Conv2D)               (None, 185, 4, 32)   1568        input_1[0][0]                    \n",
      "__________________________________________________________________________________________________\n",
      "conv2d_5 (Conv2D)               (None, 189, 4, 32)   1184        input_1[0][0]                    \n",
      "__________________________________________________________________________________________________\n",
      "conv2d_7 (Conv2D)               (None, 193, 4, 32)   800         input_1[0][0]                    \n",
      "__________________________________________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2D)  (None, 9, 4, 32)     0           conv2d_1[0][0]                   \n",
      "__________________________________________________________________________________________________\n",
      "max_pooling2d_3 (MaxPooling2D)  (None, 9, 4, 32)     0           conv2d_3[0][0]                   \n",
      "__________________________________________________________________________________________________\n",
      "max_pooling2d_5 (MaxPooling2D)  (None, 9, 4, 32)     0           conv2d_5[0][0]                   \n",
      "__________________________________________________________________________________________________\n",
      "max_pooling2d_7 (MaxPooling2D)  (None, 9, 4, 32)     0           conv2d_7[0][0]                   \n",
      "__________________________________________________________________________________________________\n",
      "conv2d_2 (Conv2D)               (None, 7, 4, 64)     6208        max_pooling2d_1[0][0]            \n",
      "__________________________________________________________________________________________________\n",
      "conv2d_4 (Conv2D)               (None, 6, 4, 64)     8256        max_pooling2d_3[0][0]            \n",
      "__________________________________________________________________________________________________\n",
      "conv2d_6 (Conv2D)               (None, 5, 4, 64)     10304       max_pooling2d_5[0][0]            \n",
      "__________________________________________________________________________________________________\n",
      "conv2d_8 (Conv2D)               (None, 4, 4, 64)     12352       max_pooling2d_7[0][0]            \n",
      "__________________________________________________________________________________________________\n",
      "max_pooling2d_2 (MaxPooling2D)  (None, 1, 4, 64)     0           conv2d_2[0][0]                   \n",
      "__________________________________________________________________________________________________\n",
      "max_pooling2d_4 (MaxPooling2D)  (None, 1, 4, 64)     0           conv2d_4[0][0]                   \n",
      "__________________________________________________________________________________________________\n",
      "max_pooling2d_6 (MaxPooling2D)  (None, 1, 4, 64)     0           conv2d_6[0][0]                   \n",
      "__________________________________________________________________________________________________\n",
      "max_pooling2d_8 (MaxPooling2D)  (None, 1, 4, 64)     0           conv2d_8[0][0]                   \n",
      "__________________________________________________________________________________________________\n",
      "flatten_1 (Flatten)             (None, 256)          0           max_pooling2d_2[0][0]            \n",
      "__________________________________________________________________________________________________\n",
      "flatten_2 (Flatten)             (None, 256)          0           max_pooling2d_4[0][0]            \n",
      "__________________________________________________________________________________________________\n",
      "flatten_3 (Flatten)             (None, 256)          0           max_pooling2d_6[0][0]            \n",
      "__________________________________________________________________________________________________\n",
      "flatten_4 (Flatten)             (None, 256)          0           max_pooling2d_8[0][0]            \n",
      "__________________________________________________________________________________________________\n",
      "concatenate_1 (Concatenate)     (None, 1024)         0           flatten_1[0][0]                  \n",
      "                                                                 flatten_2[0][0]                  \n",
      "                                                                 flatten_3[0][0]                  \n",
      "                                                                 flatten_4[0][0]                  \n",
      "__________________________________________________________________________________________________\n",
      "dropout_1 (Dropout)             (None, 1024)         0           concatenate_1[0][0]              \n",
      "__________________________________________________________________________________________________\n",
      "dense_1 (Dense)                 (None, 128)          131200      dropout_1[0][0]                  \n",
      "__________________________________________________________________________________________________\n",
      "dropout_2 (Dropout)             (None, 128)          0           dense_1[0][0]                    \n",
      "__________________________________________________________________________________________________\n",
      "dense_2 (Dense)                 (None, 16)           2064        dropout_2[0][0]                  \n",
      "==================================================================================================\n",
      "Total params: 175,888\n",
      "Trainable params: 175,888\n",
      "Non-trainable params: 0\n",
      "__________________________________________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "def CNN(input_shape=(200,6,1), classes=16): \n",
    "    X_input = Input(input_shape)\n",
    "    \n",
    "    f1 = [20, 16, 12, 8]\n",
    "    f2 = [3, 4, 5, 6]\n",
    "    convs = []\n",
    "    \n",
    "    for i in range(4):\n",
    "        x = Conv2D(filters=32, kernel_size=(f1[i],3), strides=(1,1), activation='relu',padding='valid')(X_input)\n",
    "        x = MaxPooling2D((20,1))(x)\n",
    "        \n",
    "        x = Conv2D(filters=64, kernel_size=(f2[i],1), strides=(1,1), activation='relu', padding='valid')(x)\n",
    "        x = MaxPooling2D((9-2-i,1))(x)\n",
    "        \n",
    "        x = Flatten()(x)\n",
    "        convs.append(x)\n",
    "        \n",
    "    merge = concatenate(convs,axis=1)\n",
    "    X = merge\n",
    "    X = Dropout(0.5)(X)\n",
    "    X = Dense(128,activation='relu')(X)\n",
    "    X = Dropout(0.5)(X)\n",
    "    X = Dense(classes, activation='softmax')(X)\n",
    "    model = Model(inputs=X_input, outputs=X)\n",
    "    return model\n",
    "    \n",
    "model = CNN()\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 训练原始数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 3827 samples, validate on 957 samples\n",
      "Epoch 1/100\n",
      "3827/3827 [==============================] - 4s 939us/step - loss: 2.4755 - acc: 0.1769 - val_loss: 1.7273 - val_acc: 0.4744\n",
      "Epoch 2/100\n",
      "3827/3827 [==============================] - 2s 629us/step - loss: 1.6431 - acc: 0.4311 - val_loss: 1.1524 - val_acc: 0.6290\n",
      "Epoch 3/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 1.2655 - acc: 0.5469 - val_loss: 0.9250 - val_acc: 0.7001\n",
      "Epoch 4/100\n",
      "3827/3827 [==============================] - 2s 616us/step - loss: 1.0566 - acc: 0.6290 - val_loss: 0.7361 - val_acc: 0.7816\n",
      "Epoch 5/100\n",
      "3827/3827 [==============================] - 2s 603us/step - loss: 0.8920 - acc: 0.6864 - val_loss: 0.6241 - val_acc: 0.7931\n",
      "Epoch 6/100\n",
      "3827/3827 [==============================] - 2s 601us/step - loss: 0.7643 - acc: 0.7209 - val_loss: 0.5683 - val_acc: 0.8004\n",
      "Epoch 7/100\n",
      "3827/3827 [==============================] - 2s 603us/step - loss: 0.7086 - acc: 0.7465 - val_loss: 0.5045 - val_acc: 0.8307\n",
      "Epoch 8/100\n",
      "3827/3827 [==============================] - 2s 597us/step - loss: 0.6471 - acc: 0.7748 - val_loss: 0.4834 - val_acc: 0.8349\n",
      "Epoch 9/100\n",
      "3827/3827 [==============================] - 2s 603us/step - loss: 0.5805 - acc: 0.7930 - val_loss: 0.4430 - val_acc: 0.8537\n",
      "Epoch 10/100\n",
      "3827/3827 [==============================] - 2s 612us/step - loss: 0.5402 - acc: 0.8082 - val_loss: 0.4275 - val_acc: 0.8600\n",
      "Epoch 11/100\n",
      "3827/3827 [==============================] - 2s 605us/step - loss: 0.5087 - acc: 0.8145 - val_loss: 0.4023 - val_acc: 0.8600\n",
      "Epoch 12/100\n",
      "3827/3827 [==============================] - 2s 597us/step - loss: 0.4783 - acc: 0.8252 - val_loss: 0.3839 - val_acc: 0.8631\n",
      "Epoch 13/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 0.4569 - acc: 0.8317 - val_loss: 0.3585 - val_acc: 0.8736\n",
      "Epoch 14/100\n",
      "3827/3827 [==============================] - 2s 592us/step - loss: 0.4331 - acc: 0.8430 - val_loss: 0.3717 - val_acc: 0.8704\n",
      "Epoch 15/100\n",
      "3827/3827 [==============================] - 2s 599us/step - loss: 0.4321 - acc: 0.8443 - val_loss: 0.3558 - val_acc: 0.8830\n",
      "Epoch 16/100\n",
      "3827/3827 [==============================] - 2s 596us/step - loss: 0.4034 - acc: 0.8474 - val_loss: 0.3308 - val_acc: 0.8819\n",
      "Epoch 17/100\n",
      "3827/3827 [==============================] - 2s 595us/step - loss: 0.3841 - acc: 0.8539 - val_loss: 0.3555 - val_acc: 0.8694\n",
      "Epoch 18/100\n",
      "3827/3827 [==============================] - 2s 598us/step - loss: 0.3815 - acc: 0.8573 - val_loss: 0.3172 - val_acc: 0.8871\n",
      "Epoch 19/100\n",
      "3827/3827 [==============================] - 2s 593us/step - loss: 0.3760 - acc: 0.8581 - val_loss: 0.3232 - val_acc: 0.8851\n",
      "Epoch 20/100\n",
      "3827/3827 [==============================] - 2s 592us/step - loss: 0.3587 - acc: 0.8673 - val_loss: 0.3190 - val_acc: 0.8788\n",
      "Epoch 21/100\n",
      "3827/3827 [==============================] - 2s 589us/step - loss: 0.3464 - acc: 0.8709 - val_loss: 0.3160 - val_acc: 0.8851\n",
      "Epoch 22/100\n",
      "3827/3827 [==============================] - 2s 598us/step - loss: 0.3387 - acc: 0.8636 - val_loss: 0.3084 - val_acc: 0.8809\n",
      "Epoch 23/100\n",
      "3827/3827 [==============================] - 2s 587us/step - loss: 0.3269 - acc: 0.8777 - val_loss: 0.2930 - val_acc: 0.8913\n",
      "Epoch 24/100\n",
      "3827/3827 [==============================] - 2s 599us/step - loss: 0.3226 - acc: 0.8780 - val_loss: 0.2942 - val_acc: 0.8986\n",
      "Epoch 25/100\n",
      "3827/3827 [==============================] - 2s 592us/step - loss: 0.3214 - acc: 0.8840 - val_loss: 0.2979 - val_acc: 0.8986\n",
      "Epoch 26/100\n",
      "3827/3827 [==============================] - 2s 597us/step - loss: 0.3071 - acc: 0.8816 - val_loss: 0.2926 - val_acc: 0.8903\n",
      "Epoch 27/100\n",
      "3827/3827 [==============================] - 2s 592us/step - loss: 0.2938 - acc: 0.8856 - val_loss: 0.2849 - val_acc: 0.8955\n",
      "Epoch 28/100\n",
      "3827/3827 [==============================] - 2s 596us/step - loss: 0.2953 - acc: 0.8876 - val_loss: 0.2946 - val_acc: 0.8966\n",
      "Epoch 29/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 0.2840 - acc: 0.8929 - val_loss: 0.2866 - val_acc: 0.8924\n",
      "Epoch 30/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 0.2728 - acc: 0.8973 - val_loss: 0.2777 - val_acc: 0.9070\n",
      "Epoch 31/100\n",
      "3827/3827 [==============================] - 2s 592us/step - loss: 0.2627 - acc: 0.8970 - val_loss: 0.2745 - val_acc: 0.9070\n",
      "Epoch 32/100\n",
      "3827/3827 [==============================] - 2s 596us/step - loss: 0.2771 - acc: 0.8923 - val_loss: 0.3116 - val_acc: 0.8819\n",
      "Epoch 33/100\n",
      "3827/3827 [==============================] - 2s 589us/step - loss: 0.2581 - acc: 0.8963 - val_loss: 0.2918 - val_acc: 0.9039\n",
      "Epoch 34/100\n",
      "3827/3827 [==============================] - 2s 593us/step - loss: 0.2677 - acc: 0.8947 - val_loss: 0.2818 - val_acc: 0.8966\n",
      "Epoch 35/100\n",
      "3827/3827 [==============================] - 2s 593us/step - loss: 0.2544 - acc: 0.8976 - val_loss: 0.2802 - val_acc: 0.8997\n",
      "Epoch 36/100\n",
      "3827/3827 [==============================] - 2s 609us/step - loss: 0.2423 - acc: 0.9038 - val_loss: 0.2827 - val_acc: 0.8955\n",
      "Epoch 37/100\n",
      "3827/3827 [==============================] - 2s 603us/step - loss: 0.2394 - acc: 0.9062 - val_loss: 0.2816 - val_acc: 0.8997\n",
      "Epoch 38/100\n",
      "3827/3827 [==============================] - 2s 593us/step - loss: 0.2255 - acc: 0.9151 - val_loss: 0.2731 - val_acc: 0.9049\n",
      "Epoch 39/100\n",
      "3827/3827 [==============================] - 2s 597us/step - loss: 0.2253 - acc: 0.9119 - val_loss: 0.2685 - val_acc: 0.8934\n",
      "Epoch 40/100\n",
      "3827/3827 [==============================] - 2s 588us/step - loss: 0.2272 - acc: 0.9127 - val_loss: 0.2758 - val_acc: 0.9080\n",
      "Epoch 41/100\n",
      "3827/3827 [==============================] - 2s 600us/step - loss: 0.2264 - acc: 0.9156 - val_loss: 0.2757 - val_acc: 0.8997\n",
      "Epoch 42/100\n",
      "3827/3827 [==============================] - 2s 599us/step - loss: 0.2249 - acc: 0.9127 - val_loss: 0.2620 - val_acc: 0.9028\n",
      "Epoch 43/100\n",
      "3827/3827 [==============================] - 2s 599us/step - loss: 0.2147 - acc: 0.9177 - val_loss: 0.2590 - val_acc: 0.9060\n",
      "Epoch 44/100\n",
      "3827/3827 [==============================] - 2s 594us/step - loss: 0.2172 - acc: 0.9122 - val_loss: 0.2658 - val_acc: 0.8924\n",
      "Epoch 45/100\n",
      "3827/3827 [==============================] - 2s 595us/step - loss: 0.2105 - acc: 0.9161 - val_loss: 0.2557 - val_acc: 0.9039\n",
      "Epoch 46/100\n",
      "3827/3827 [==============================] - 2s 588us/step - loss: 0.2093 - acc: 0.9161 - val_loss: 0.2716 - val_acc: 0.9049\n",
      "Epoch 47/100\n",
      "3827/3827 [==============================] - 2s 589us/step - loss: 0.2065 - acc: 0.9198 - val_loss: 0.2917 - val_acc: 0.8986\n",
      "Epoch 48/100\n",
      "3827/3827 [==============================] - 2s 600us/step - loss: 0.2024 - acc: 0.9195 - val_loss: 0.2830 - val_acc: 0.9028\n",
      "Epoch 49/100\n",
      "3827/3827 [==============================] - 2s 600us/step - loss: 0.1991 - acc: 0.9198 - val_loss: 0.2830 - val_acc: 0.8976\n",
      "Epoch 50/100\n",
      "3827/3827 [==============================] - 2s 595us/step - loss: 0.2082 - acc: 0.9169 - val_loss: 0.2604 - val_acc: 0.9080\n",
      "Epoch 51/100\n",
      "3827/3827 [==============================] - 2s 588us/step - loss: 0.1932 - acc: 0.9193 - val_loss: 0.2814 - val_acc: 0.8997\n",
      "Epoch 52/100\n",
      "3827/3827 [==============================] - 2s 593us/step - loss: 0.2018 - acc: 0.9206 - val_loss: 0.2633 - val_acc: 0.9185\n",
      "Epoch 53/100\n",
      "3827/3827 [==============================] - 2s 594us/step - loss: 0.1938 - acc: 0.9234 - val_loss: 0.3262 - val_acc: 0.8945\n",
      "Epoch 54/100\n",
      "3827/3827 [==============================] - 2s 601us/step - loss: 0.1807 - acc: 0.9258 - val_loss: 0.2952 - val_acc: 0.9039\n",
      "Epoch 55/100\n",
      "3827/3827 [==============================] - 2s 599us/step - loss: 0.1819 - acc: 0.9276 - val_loss: 0.2542 - val_acc: 0.9060\n",
      "Epoch 56/100\n",
      "3827/3827 [==============================] - 2s 595us/step - loss: 0.1765 - acc: 0.9300 - val_loss: 0.2809 - val_acc: 0.9049\n",
      "Epoch 57/100\n",
      "3827/3827 [==============================] - 2s 596us/step - loss: 0.1785 - acc: 0.9261 - val_loss: 0.2645 - val_acc: 0.9007\n",
      "Epoch 58/100\n",
      "3827/3827 [==============================] - 2s 589us/step - loss: 0.1763 - acc: 0.9281 - val_loss: 0.2594 - val_acc: 0.9049\n",
      "Epoch 59/100\n",
      "3827/3827 [==============================] - 2s 590us/step - loss: 0.1876 - acc: 0.9271 - val_loss: 0.2688 - val_acc: 0.9060\n",
      "Epoch 60/100\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3827/3827 [==============================] - 2s 597us/step - loss: 0.1753 - acc: 0.9323 - val_loss: 0.2833 - val_acc: 0.9122\n",
      "Epoch 61/100\n",
      "3827/3827 [==============================] - 2s 604us/step - loss: 0.1644 - acc: 0.9347 - val_loss: 0.2374 - val_acc: 0.9154\n",
      "Epoch 62/100\n",
      "3827/3827 [==============================] - 2s 592us/step - loss: 0.1669 - acc: 0.9331 - val_loss: 0.2844 - val_acc: 0.9091\n",
      "Epoch 63/100\n",
      "3827/3827 [==============================] - 2s 593us/step - loss: 0.1550 - acc: 0.9373 - val_loss: 0.2610 - val_acc: 0.9122\n",
      "Epoch 64/100\n",
      "3827/3827 [==============================] - 2s 596us/step - loss: 0.1589 - acc: 0.9378 - val_loss: 0.2984 - val_acc: 0.8955\n",
      "Epoch 65/100\n",
      "3827/3827 [==============================] - 2s 602us/step - loss: 0.1672 - acc: 0.9313 - val_loss: 0.2620 - val_acc: 0.9039\n",
      "Epoch 66/100\n",
      "3827/3827 [==============================] - 2s 594us/step - loss: 0.1669 - acc: 0.9352 - val_loss: 0.2981 - val_acc: 0.9101\n",
      "Epoch 67/100\n",
      "3827/3827 [==============================] - 2s 595us/step - loss: 0.1807 - acc: 0.9292 - val_loss: 0.2776 - val_acc: 0.9039\n",
      "Epoch 68/100\n",
      "3827/3827 [==============================] - 2s 598us/step - loss: 0.1469 - acc: 0.9378 - val_loss: 0.2861 - val_acc: 0.9070\n",
      "Epoch 69/100\n",
      "3827/3827 [==============================] - 2s 598us/step - loss: 0.1493 - acc: 0.9409 - val_loss: 0.2734 - val_acc: 0.9133\n",
      "Epoch 70/100\n",
      "3827/3827 [==============================] - 2s 595us/step - loss: 0.1568 - acc: 0.9360 - val_loss: 0.2673 - val_acc: 0.9122\n",
      "Epoch 71/100\n",
      "3827/3827 [==============================] - 2s 589us/step - loss: 0.1503 - acc: 0.9362 - val_loss: 0.2660 - val_acc: 0.9112\n",
      "Epoch 72/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 0.1535 - acc: 0.9420 - val_loss: 0.2780 - val_acc: 0.9122\n",
      "Epoch 73/100\n",
      "3827/3827 [==============================] - 2s 594us/step - loss: 0.1515 - acc: 0.9420 - val_loss: 0.3064 - val_acc: 0.9039\n",
      "Epoch 74/100\n",
      "3827/3827 [==============================] - 2s 602us/step - loss: 0.1532 - acc: 0.9396 - val_loss: 0.2621 - val_acc: 0.9060\n",
      "Epoch 75/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 0.1549 - acc: 0.9415 - val_loss: 0.2593 - val_acc: 0.9175\n",
      "Epoch 76/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 0.1421 - acc: 0.9441 - val_loss: 0.2764 - val_acc: 0.9154\n",
      "Epoch 77/100\n",
      "3827/3827 [==============================] - 2s 593us/step - loss: 0.1452 - acc: 0.9459 - val_loss: 0.2920 - val_acc: 0.9060\n",
      "Epoch 78/100\n",
      "3827/3827 [==============================] - 2s 594us/step - loss: 0.1336 - acc: 0.9477 - val_loss: 0.2656 - val_acc: 0.9060\n",
      "Epoch 79/100\n",
      "3827/3827 [==============================] - 2s 587us/step - loss: 0.1395 - acc: 0.9436 - val_loss: 0.2913 - val_acc: 0.9080\n",
      "Epoch 80/100\n",
      "3827/3827 [==============================] - 2s 604us/step - loss: 0.1340 - acc: 0.9462 - val_loss: 0.2899 - val_acc: 0.9164\n",
      "Epoch 81/100\n",
      "3827/3827 [==============================] - 2s 599us/step - loss: 0.1361 - acc: 0.9480 - val_loss: 0.2752 - val_acc: 0.9112\n",
      "Epoch 82/100\n",
      "3827/3827 [==============================] - 2s 592us/step - loss: 0.1481 - acc: 0.9425 - val_loss: 0.2812 - val_acc: 0.9143\n",
      "Epoch 83/100\n",
      "3827/3827 [==============================] - 2s 592us/step - loss: 0.1280 - acc: 0.9511 - val_loss: 0.2754 - val_acc: 0.9112\n",
      "Epoch 84/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 0.1302 - acc: 0.9483 - val_loss: 0.2642 - val_acc: 0.9122\n",
      "Epoch 85/100\n",
      "3827/3827 [==============================] - 2s 597us/step - loss: 0.1286 - acc: 0.9527 - val_loss: 0.2790 - val_acc: 0.9080\n",
      "Epoch 86/100\n",
      "3827/3827 [==============================] - 2s 607us/step - loss: 0.1356 - acc: 0.9446 - val_loss: 0.2700 - val_acc: 0.9154\n",
      "Epoch 87/100\n",
      "3827/3827 [==============================] - 2s 594us/step - loss: 0.1359 - acc: 0.9480 - val_loss: 0.3333 - val_acc: 0.8966\n",
      "Epoch 88/100\n",
      "3827/3827 [==============================] - 2s 592us/step - loss: 0.1319 - acc: 0.9498 - val_loss: 0.2710 - val_acc: 0.9060\n",
      "Epoch 89/100\n",
      "3827/3827 [==============================] - 2s 595us/step - loss: 0.1282 - acc: 0.9545 - val_loss: 0.3076 - val_acc: 0.9070\n",
      "Epoch 90/100\n",
      "3827/3827 [==============================] - 2s 594us/step - loss: 0.1231 - acc: 0.9524 - val_loss: 0.2846 - val_acc: 0.9039\n",
      "Epoch 91/100\n",
      "3827/3827 [==============================] - 2s 593us/step - loss: 0.1155 - acc: 0.9561 - val_loss: 0.2587 - val_acc: 0.9133\n",
      "Epoch 92/100\n",
      "3827/3827 [==============================] - 2s 612us/step - loss: 0.1150 - acc: 0.9564 - val_loss: 0.2793 - val_acc: 0.8986\n",
      "Epoch 93/100\n",
      "3827/3827 [==============================] - 2s 590us/step - loss: 0.1276 - acc: 0.9537 - val_loss: 0.2818 - val_acc: 0.9143\n",
      "Epoch 94/100\n",
      "3827/3827 [==============================] - 2s 601us/step - loss: 0.1173 - acc: 0.9540 - val_loss: 0.2697 - val_acc: 0.9112\n",
      "Epoch 95/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 0.1138 - acc: 0.9553 - val_loss: 0.3086 - val_acc: 0.9101\n",
      "Epoch 96/100\n",
      "3827/3827 [==============================] - 2s 591us/step - loss: 0.1112 - acc: 0.9595 - val_loss: 0.2775 - val_acc: 0.9143\n",
      "Epoch 97/100\n",
      "3827/3827 [==============================] - 2s 600us/step - loss: 0.1234 - acc: 0.9540 - val_loss: 0.2875 - val_acc: 0.9122\n",
      "Epoch 98/100\n",
      "3827/3827 [==============================] - 2s 606us/step - loss: 0.1050 - acc: 0.9613 - val_loss: 0.3171 - val_acc: 0.9049\n",
      "Epoch 99/100\n",
      "3827/3827 [==============================] - 2s 596us/step - loss: 0.1143 - acc: 0.9579 - val_loss: 0.2911 - val_acc: 0.9133\n",
      "Epoch 100/100\n",
      "3827/3827 [==============================] - 2s 599us/step - loss: 0.1127 - acc: 0.9564 - val_loss: 0.2871 - val_acc: 0.9206\n",
      "3827/3827 [==============================] - 1s 228us/step\n",
      "Train Loss = 0.03849437078867455\n",
      "Train Accuracy = 0.9916383590279593\n",
      "957/957 [==============================] - 0s 230us/step\n",
      "Test Loss = 0.2871323648291322\n",
      "Test Accuracy = 0.9205851614039271\n",
      "time: 231.79616594314575\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "start = time.time()\n",
    "\n",
    "model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "history = LossHistory() # 创建一个history实例\n",
    "model.fit(X_train, Y_train, epochs=100, validation_data=(X_test, Y_test),batch_size=64,callbacks=[history])\n",
    "\n",
    "preds_train = model.evaluate(X_train, Y_train)\n",
    "print(\"Train Loss = \" + str(preds_train[0]))\n",
    "print(\"Train Accuracy = \" + str(preds_train[1]))\n",
    "\n",
    "preds_test  = model.evaluate(X_test, Y_test)\n",
    "print(\"Test Loss = \" + str(preds_test[0]))\n",
    "print(\"Test Accuracy = \" + str(preds_test[1]))\n",
    "\n",
    "end = time.time()\n",
    "print(\"time:\",end-start)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fc70f1b0358>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "history.loss_plot('epoch')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": "block",
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
